fn main() {
    println!("Hello, world!");
}

// 所有权规则
/*
1. 每个值只有一个所有者
2. 每个值同时只能有一个所有者
3.当所有者超出作用域， 该值就被删除

*/

// 作用域就是一个值的有效范围

fn test1() {
    let s = "aaa";
    println!("s is {}", s);
}


// String类型， 存放在堆上
// 创建字符串

#[test]
fn test_String() {
    let mut s1 = String::from("aaaa");
    println!("s1 is {}", s1);
    s1.push_str("111");
    println!("s1 is {}", s1);


    let mut s2 = "aaa";

    println!("s2 is {}", s2);
    s2 = "111111111";

    println!("s2 is {}", s2);
}


// move

#[test]
fn test_move() {
    /*
    一个String 对象包括3个部分:
    1.指向存放字符串内容的内存指针(在堆上)
    2.长度
    3.容量

    */
    let s1 = String::from("aaaa");

    let s2 = s1;  // move 之后 s1 就失效了,

    // println!("s1 is {}", s1);

    println!("s2 is {}", s2);


    let s1 = String::from("aaaa");

    let s2 = s1.clone(); // s1 不会失效

    println!("s1 is {}", s1);

    println!("s2 is {}", s2);


    let x = 5;

    let y = x;

    println!("x is {}", x);  // 不会报错，因为实现了Copy Trait

    println!("y is {}", y);


    /*
    实现了Copy Trait 的类型
    1. 所有的整数类型
    2. 所有的浮点类型
    3. 布尔类型
    4. char
    5. Tuple (如果其所有的元素都是Copy的， 且数量不超过12 )

    */
}

//所有权和函数

/*
将值传递给函数和将值赋给变量是类似的， 要不是move 要不是copy
*/
#[test]
fn test_onwer_ship() {
    let num = 11;
    println!("num is {}", num);

    test33(num);

    println!("num is {}", num);


    let str = String::from("aaaa");
    println!("str is {}", str);

    test44(str);

    // 下面这句会报错, value borrowed here after move
    // println!("str is {}", str);
}

fn test33(num: i32) {
    println!("test33---------------- num is {}", num);
}


fn test44(str: String) {
    println!("test44----------- str is {}", str);
}//   str  被释放


//   返回值和作用域

#[test]
fn fn_return_scope() {
    let s1 = gives_ownership();


    let s2 = String::from("hello world");

    let s3 = takes_and_gives_back(s2); // s2 失效了


    // println!("s2 is {}", s2);  报错  value borrowed here after move
    println!("  s1 is {} , s3 is  {}", s1, s3);
}


fn gives_ownership() -> String {
    let string = String::from("hello");
    string
}

fn takes_and_gives_back(str: String) -> String {
    str
}


// 引用和借用
#[test]
fn test_ref() {
    let mut s1 = String::from("hello ");

    let len = calculate_len(&mut s1);

    println!(" str is {} , length is {}  ", s1, len);   // s1  没有失效
}

fn calculate_len(str: &mut String) -> usize {
    str.push_str("aaaa");
    let len = str.len();
    len
}


// 可变引用
/*
在一个作用域里面， 一个数据只能有一个可变引用， 下面的代码会报错
*/


#[test]
fn test_mut_ref1() {
    let mut s1 = String::from("hello ");

    let s2 = &mut s1;

    let s3 = &mut s1; //   这里报错 second mutable borrow occurs here   (如果s2 s3 后面都没有用到， 不会报错)

    //  rust 1.77.2  编译不会报错


    println!(" s2 is    ");
}


// 2个可变引用不在一个作用域， 就不会报错
#[test]
fn test_mut_ref2() {
    let mut s1 = String::from("hello ");


    // 2个可变引用不在一个作用域， 就不会报错
    {
        let s3 = &mut s1;
        println!("s3 is {}", s3)
    }// s3 出了作用域 就失效了

    let s2 = &mut s1;
    println!(" s2 is    {}", s2);
}


// 可变引用和不可变引用不能同时存在
#[test]
fn test_mut_ref3() {
    let mut s1 = String::from("hello ");

    let s3 = &s1;

    // let s2 = &mut s1;  //    报错   mutable borrow occurs here
    // println!(" s2 is    {}", s2);

    println!("s3 is {}", s3);
}


// 切片   另一种不持有所有权的数据类型

#[test]
fn test_sclice() {
    let mut str = String::from("hello world");

    let first = first_world(&str[ .. ]);

    str.clear();
    // println!("first is {}", first);  //   这一句会报错， 因为 str.clear()   将 str 释放了， first 是 str的引用


    let str = "hello worrr";

    let first = first_world(str);

    println!("str is {} ,  first is {}",str ,  first); //    str 的所有权 还在

    









}

fn first_world(str: &str) -> &str {
    let array = str.as_bytes();
    for (index, &ch) in array.iter().enumerate() {
        if ch == b' ' {
            return &str[0..index];
        }
    }
    &str[..]
}






